using System.Runtime.InteropServices;
using glTFLoader.Schema;
using Newtonsoft.Json;

namespace test_sample_generate
{
    [TestClass]
    public class UnitTest1
    {
        Gltf gltf = glTFLoader.Interface.LoadModel("../../../test/torus.gltf");
        Gltf gltf1 = glTFLoader.Interface.LoadModel("../../../test/cylinder.gltf");

        [TestMethod]
        public void TestMethod1()
        {
            Gltf gltf = glTFLoader.Interface.LoadModel("../../../test/torus.gltf");
            Gltf gltf1 = glTFLoader.Interface.LoadModel("../../../test/cylinder.gltf");

            string EXT_mesh_gpu_instancing = @"
                {
                    ""attributes"" : {
                      ""TRANSLATION"" : 4,
                      ""ROTATION"" : 5,
                      ""SCALE"" : 6
                    }
                }
            ";
            gltf.Nodes[0].Extensions = new Dictionary<string, object>();
            gltf.Nodes[0].Extensions.TryAdd(
                "EXT_mesh_gpu_instancing",
                JsonConvert.DeserializeObject(EXT_mesh_gpu_instancing));

            string EXT_mesh_gpu_instancing1 = @"
                {
                    ""attributes"" : {
                      ""TRANSLATION"" : 4,
                      ""ROTATION"" : 5,
                      ""SCALE"" : 6
                    }
                }
            ";
            gltf1.Nodes[0].Extensions = new Dictionary<string, object>();
            gltf1.Nodes[0].Extensions.TryAdd(
                "EXT_mesh_gpu_instancing",
                JsonConvert.DeserializeObject(EXT_mesh_gpu_instancing1));

            return;
        }

        [TestMethod]
        public void Test0()
        {
            float[] baseTranslation = new float[] { 0f, 0f, 0f }; float[] baseRotation = new float[] { .707f, 0f, .707f, 0f }; float[] baseScale = new float[] { .9f, .9f, .3f };
            float[] baseTranslation1 = new float[] { 0f, 0f, 0f }; float[] baseRotation1 = new float[] { 0f, 0f, .707f, .707f }; float[] baseScale1 = new float[] { .5f, 1f, .5f };

            List<Node> target = new List<Node>();
            List<Node> target1 = new List<Node>();
            for (int i = 0; i < 25; i++)
            {
                target.Add(new Node { Translation = baseTranslation.ToArray(), Rotation = baseRotation.ToArray(), Scale = baseScale.ToArray(), Mesh = 0 });
                target1.Add(new Node { Translation = baseTranslation1.ToArray(), Rotation = baseRotation1.ToArray(), Scale = baseScale1.ToArray(), Mesh = 0 });
            }
            Node sceneNode = new Node
            {
                Name = "RootNode",
                Children = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 }
            };
            target.Add(sceneNode);
            gltf.Nodes = target.ToArray();
            gltf.Scenes[0].Nodes[0] = 25;
            Node sceneNode1 = new Node
            {
                Name = "RootNode",
                Children = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 }
            };
            target1.Add(sceneNode1);
            gltf1.Nodes = target1.ToArray();
            gltf1.Scenes[0].Nodes[0] = 25;

            SetTranslation();

            SetRotation();

            SetScale();

            glTFLoader.Interface.SaveModel(gltf, "../../../test/torus1.gltf");
            glTFLoader.Interface.SaveModel(gltf1, "../../../test/cylinder1.gltf");

            return;
        }

        [TestMethod]
        public void Test1()
        {
            string json = @"
{
  ""asset"" : {
    ""version"" : ""1.1""
  },
  ""geometricError"" : 100.0,
  ""root"" : {
    ""content"" : {
      ""uri"" : ""torus1.gltf""
    },
    ""boundingVolume"" : {
      ""box"" : [ 
         6.707386, -5.8532143, 5.8532143, 
         6.707386, 0.0, 0.0, 
         0.0, -5.8532143, 0.0, 
         0.0, 0.0, 5.8532143
      ]
    },
    ""geometricError"" : 0.0
  }
}";
            string json1 = @"
{
  ""asset"" : {
    ""version"" : ""1.1""
  },
  ""geometricError"" : 100.0,
  ""root"" : {
    ""content"" : {
      ""uri"" : ""cylinder1.gltf""
    },
    ""boundingVolume"" : {
      ""box"" : [ 
         6.707386, -5.8532143, 5.8532143, 
         6.707386, 0.0, 0.0, 
         0.0, -5.8532143, 0.0, 
         0.0, 0.0, 5.8532143
      ]
    },
    ""geometricError"" : 0.0
  }
}";
            string json2 = @"
{
  ""asset"": {
    ""version"": ""1.1""
  },
  ""geometricError"": 100,
  ""root"": {
    ""boundingVolume"" : {
      ""box"" : [ 
         6.707386, -5.8532143, 5.8532143, 
         6.707386, 0.0, 0.0, 
         0.0, -5.8532143, 0.0, 
         0.0, 0.0, 5.8532143
      ]
    },
    ""geometricError"": 70,
    ""children"": [
      {
        ""boundingVolume"" : {
          ""box"" : [ 
             6.707386, -5.8532143, 5.8532143, 
             6.707386, 0.0, 0.0, 
             0.0, -5.8532143, 0.0, 
             0.0, 0.0, 5.8532143
          ]
        },
        ""geometricError"": 0,
        ""content"": {
          ""uri"": ""./tileset.json""
        }
      },
      {
        ""boundingVolume"" : {
          ""box"" : [ 
             6.707386, -5.8532143, 5.8532143, 
             6.707386, 0.0, 0.0, 
             0.0, -5.8532143, 0.0, 
             0.0, 0.0, 5.8532143
          ]
        },
        ""geometricError"": 0,
        ""content"": {
          ""uri"": ""./tileset1.json""
        }
      }
    ]
  }
}
";
            string filePath = @"../../../test/tileset.json";
            string filePath1 = @"../../../test/tileset1.json";
            string filePath2 = @"../../../test/tileset2.json";

            using (StreamWriter writer = new StreamWriter(filePath))
            {
                writer.Write(json);
            }

            using (StreamWriter writer = new StreamWriter(filePath1))
            {
                writer.Write(json1);
            }

            using (StreamWriter writer = new StreamWriter(filePath2))
            {
                writer.Write(json2);
            }

            return;
        }

        void SetTranslation()
        {
            var floats = new float[][]{
                new float[]{2.5f, 0.0f, 0.0f},
                new float[]{5.0f, 2.5f, 0.0f},
                new float[]{2.5f, 5.0f, 0.0f},
                new float[]{0.0f, 2.5f, 0.0f},
                new float[]{0.0f, 0.0f, 2.5f},
                new float[]{5.0f, 0.0f, 2.5f},
                new float[]{5.0f, 5.0f, 2.5f},
                new float[]{0.0f, 5.0f, 2.5f},
                new float[]{2.5f, 0.0f, 5.0f},
                new float[]{5.0f, 2.5f, 5.0f},
                new float[]{2.5f, 5.0f, 5.0f},
                new float[]{0.0f, 2.5f, 5.0f },

                new float[]{20.0f, 0.0f, 0.0f },
                new float[]{30.0f, 10.0f, 0.0f },
                new float[]{20.0f, 20.0f, 0.0f},
                new float[]{10.0f, 10.0f, 0.0f},
                new float[]{10.0f, 0.0f, 10.0f},
                new float[]{30.0f, 0.0f, 10.0f},
                new float[]{30.0f, 20.0f, 10.0f },
                new float[]{10.0f, 20.0f, 10.0f},
                new float[]{20.0f, 0.0f, 20.0f },
                new float[]{30.0f, 10.0f, 20.0f },
                new float[]{20.0f, 20.0f, 20.0f},
                new float[]{10.0f, 10.0f, 20.0f},

                new float[]{- 5.0f, 0.0f, 0.0f }
            };
            for (int i = 0; i < floats.Length; i++)
            {
                gltf1.Nodes[i].Translation[0] += floats[i][0];
                gltf1.Nodes[i].Translation[1] += floats[i][1];
                gltf1.Nodes[i].Translation[2] += floats[i][2];
            }

            var floats1 = new float[][]
            {
                new float[]{2.5f, 0.0f, 0.0f},
                new float[]{5.0f, 2.5f, 0.0f},
                new float[]{2.5f, 5.0f, 0.0f},
                new float[]{0.0f, 2.5f, 0.0f},
                new float[]{0.0f, 0.0f, 2.5f},
                new float[]{5.0f, 0.0f, 2.5f},
                new float[]{5.0f, 5.0f, 2.5f},
                new float[]{0.0f, 5.0f, 2.5f},
                new float[]{2.5f, 0.0f, 5.0f},
                new float[]{5.0f, 2.5f, 5.0f},
                new float[]{2.5f, 5.0f, 5.0f},
                new float[]{0.0f, 2.5f, 5.0f },

                new float[]{20.0f, 0.0f, 0.0f },
                new float[]{30.0f, 10.0f, 0.0f },
                new float[]{20.0f, 20.0f, 0.0f},
                new float[]{10.0f, 10.0f, 0.0f},
                new float[]{10.0f, 0.0f, 10.0f},
                new float[]{30.0f, 0.0f, 10.0f},
                new float[]{30.0f, 20.0f, 10.0f },
                new float[]{10.0f, 20.0f, 10.0f},
                new float[]{20.0f, 0.0f, 20.0f },
                new float[]{30.0f, 10.0f, 20.0f },
                new float[]{20.0f, 20.0f, 20.0f},
                new float[]{10.0f, 10.0f, 20.0f},

                new float[]{- 5.0f, 0.0f, 0.0f }
            };
            for (int i = 0; i < floats1.Length; i++)
            {
                gltf.Nodes[i].Translation[0] += floats1[i][0];
                gltf.Nodes[i].Translation[1] += floats1[i][1];
                gltf.Nodes[i].Translation[2] += floats1[i][2];
            }

            return;
        }

        void SetRotation()
        {
            var floats = new float[][]{
                new float[]{ .707f, 0f, .707f, 0f },
                new float[]{.707f, 0f, 0f, .707f },
                new float[]{ .707f, 0f, .707f, 0f },
                new float[]{.707f, 0f, 0f, .707f },
                new float[]{ .707f, -.707f, 0f, 0f },
                new float[]{ .707f, -.707f, 0f, 0f },
                new float[]{ .707f, -.707f, 0f, 0f },
                new float[]{ .707f, -.707f, 0f, 0f },
                new float[]{ .707f, 0f, .707f, 0f },
                new float[]{.707f, 0f, 0f, .707f },
                new float[]{ .707f, 0f, .707f, 0f },
                new float[]{.707f, 0f, 0f, .707f },

                new float[]{ .707f, 0f, .707f, 0f },
                new float[]{.707f, 0f, 0f, .707f },
                new float[]{ .707f, 0f, .707f, 0f },
                new float[]{.707f, 0f, 0f, .707f },
                new float[]{ .707f, -.707f, 0f, 0f },
                new float[]{ .707f, -.707f, 0f, 0f },
                new float[]{ .707f, -.707f, 0f, 0f },
                new float[]{ .707f, -.707f, 0f, 0f },
                new float[]{ .707f, 0f, .707f, 0f },
                new float[]{.707f, 0f, 0f, .707f },
                new float[]{ .707f, 0f, .707f, 0f },
                new float[]{.707f, 0f, 0f, .707f },

                //new float[]{ .707f, 0f, .707f, 0f },
            };
            for (int i = 0; i < floats.Length; i++)
            {
                gltf.Nodes[i].Rotation[0] = floats[i][0];
                gltf.Nodes[i].Rotation[1] = floats[i][1];
                gltf.Nodes[i].Rotation[2] = floats[i][2];
                gltf.Nodes[i].Rotation[3] = floats[i][3];
            }

            var floats1 = new float[][]
            {
                new float[]{ 0f, 0f, .707f, .707f },
                new float[]{0f, 0f, 0f,1f },
                new float[]{ 0f, 0f, .707f, .707f },
                new float[]{0f, 0f, 0f,1f },
                new float[]{.707f, 0f, 0f, .707f },
                new float[]{.707f, 0f, 0f, .707f },
                new float[]{.707f, 0f, 0f, .707f },
                new float[]{.707f, 0f, 0f, .707f },
                new float[]{ 0f, 0f, .707f, .707f },
                new float[]{0f, 0f, 0f,1f },
                new float[]{ 0f, 0f, .707f, .707f },
                new float[]{0f, 0f, 0f,1f },

                new float[]{ 0f, 0f, .707f, .707f },
                new float[]{0f, 0f, 0f,1f },
                new float[]{ 0f, 0f, .707f, .707f },
                new float[]{0f, 0f, 0f,1f },
                new float[]{.707f, 0f, 0f, .707f },
                new float[]{.707f, 0f, 0f, .707f },
                new float[]{.707f, 0f, 0f, .707f },
                new float[]{.707f, 0f, 0f, .707f },
                new float[]{ 0f, 0f, .707f, .707f },
                new float[]{0f, 0f, 0f,1f },
                new float[]{ 0f, 0f, .707f, .707f },
                new float[]{0f, 0f, 0f,1f },

                //new float[]{ 0f, 0f, .707f, .707f }
            };
            for (int i = 0; i < floats1.Length; i++)
            {
                gltf1.Nodes[i].Rotation[0] = floats1[i][0];
                gltf1.Nodes[i].Rotation[1] = floats1[i][1];
                gltf1.Nodes[i].Rotation[2] = floats1[i][2];
                gltf1.Nodes[i].Rotation[3] = floats1[i][3];
            }

            return;
        }

        void SetScale()
        {
            var floats = new float[][]{
                new float[]{1f,1f,1f},
                new float[]{1f,1f,1f},
                new float[]{1f,1f,1f},
                new float[]{1f,1f,1f},
                new float[]{1f,1f,1f},
                new float[]{1f,1f,1f},
                new float[]{1f,1f,1f},
                new float[]{1f,1f,1f},
                new float[]{1f,1f,1f},
                new float[]{1f,1f,1f},
                new float[]{1f,1f,1f},
                new float[]{1f,1f,1f},

                new float[]{2f,2f,1f},
                new float[]{2f,2f,1f},
                new float[]{2f,2f,1f},
                new float[]{2f,2f,1f},
                new float[]{2f,2f,1f},
                new float[]{2f,2f,1f},
                new float[]{2f,2f,1f},
                new float[]{2f,2f,1f},
                new float[]{2f,2f,1f},
                new float[]{2f,2f,1f},
                new float[]{2f,2f,1f},
                new float[]{2f,2f,1f},

                //new float[]{1f,1f,1f},
            };
            for (int i = 0; i < floats.Length; i++)
            {
                gltf.Nodes[i].Scale[0] *= floats[i][0];
                gltf.Nodes[i].Scale[1] *= floats[i][1];
                gltf.Nodes[i].Scale[2] *= floats[i][2];
            }

            var floats1 = new float[][]{
                new float[]{1f,5f,1f},
                new float[]{1f,5f,1f},
                new float[]{1f,5f,1f},
                new float[]{1f,5f,1f},
                new float[]{1f,5f,1f},
                new float[]{1f,5f,1f},
                new float[]{1f,5f,1f},
                new float[]{1f,5f,1f},
                new float[]{1f,5f,1f},
                new float[]{1f,5f,1f},
                new float[]{1f,5f,1f},
                new float[]{1f,5f,1f},

                new float[]{2f,20f,2f},
                new float[]{2f,20f,2f},
                new float[]{2f,20f,2f},
                new float[]{2f,20f,2f},
                new float[]{2f,20f,2f},
                new float[]{2f,20f,2f},
                new float[]{2f,20f,2f},
                new float[]{2f,20f,2f},
                new float[]{2f,20f,2f},
                new float[]{2f,20f,2f},
                new float[]{2f,20f,2f},
                new float[]{2f,20f,2f},

                //new float[]{1f,1f,1f},
            };
            for (int i = 0; i < floats1.Length; i++)
            {
                gltf1.Nodes[i].Scale[0] *= floats1[i][0];
                gltf1.Nodes[i].Scale[1] *= floats1[i][1];
                gltf1.Nodes[i].Scale[2] *= floats1[i][2];
            }

            return;
        }
    }
}